#include "graphics/axis_aligned_bounding_box.h"

#include "graphics/oriented_bounding_box.h"
#include "graphics/bounding_sphere.h"

namespace graphics{

bool AxisAlignedBoundingBox::Overlaps(const BoundingVolume * other) const { return other->OverlapWith(this); }
 
bool AxisAlignedBoundingBox::OverlapWith(const AxisAlignedBoundingBox * other) const {
    Vector3 other_max = other->GetMax();
    Vector3 other_min = other->GetMin();

    if( other_max[X] < max_[X] && other_max[X] > min_[X]
     && other_max[Y] < max_[Y] && other_max[Y] > min_[Y]
     && other_max[Z] < max_[Z] && other_max[Z] > min_[Z] ) {
        return true;
    } else if( other_max[X] > max_[X] && other_min[X] < max_[X]
         && other_max[Y] > max_[Y] && other_min[Y] < max_[Y]
         && other_max[Z] > max_[Z] && other_max[Z] < max_[Z] ) {
        return true;
    }
    else return false;
}

bool AxisAlignedBoundingBox::OverlapWith(const OrientedBoundingBox * other) const {
    Vector3 line = other->GetCenter() - center_;
    float distance = line.length();
     
    float closest_point_distance = abs(cml::dot(GetHalfDimension(), line)) / distance;
    
    Vector3 other_dimension = other->GetHalfDimension();        
    float other_closest_point_distance = abs(cml::dot(other_dimension, line)) / distance;

    distance -= closest_point_distance;
    distance -= other_closest_point_distance;

    if(distance <= BoundingVolume::kOverlapTolerance)
        return true;
    else return false;
}

bool AxisAlignedBoundingBox::OverlapWith(const BoundingSphere * other) const {
    Vector3 line = other->GetCenter() - center_;
    float distance = line.length();
    
             
    float closest_point_distance = abs(cml::dot(GetHalfDimension(), line)) / distance;

    distance -= closest_point_distance;
    distance -= other->GetRadius();

    if(distance <= BoundingVolume::kOverlapTolerance)
        return true;
    else return false;
}
 
} //namespace graphics